<?php
class Validation{
	protected $_data = array();
	protected $_rules = array();
	protected $_model = null;
	protected $error = array();

    /*
        格式 $rules = array(
                    array('验证的字段名',0/1/2(验证场景),'报错提示','require/in(某几种情况)/between(范围)/length(某个范围)','参数')
        );

        array('goods_name',1,'必须有商品名','require'),
        array('cat_id',1,'栏目id必须是整型值','number'),
        array('is_new',0,'in_new只能是0或1','in','0,1')
        array('goods_breif',2,'商品简介就在10到100字符','length','10,100')

    */

	public function __construct($data,$rules,$model=null){
		$this->_data=$data;
		$this->_rules=$rules;
		$this->_model=$model;
	}
	public function valid(){
		$rules=$this->_rules;
		$data=$this->_data;
		$flag=true;
		foreach($rules as $k=>$v) {
            switch($v[1]) {
                case 1://必须验证
                    if(!isset($data[$v[0]])) {
                        $this->error[] = $v[2];
                        $flag=false;
						continue;
                    }
                    if(!isset($v[4])) {
                        $v[4] = '';
                    }
                    if(!$this->check($data[$v[0]],$v[3],$v[4])) {
                        $this->error[] = $v[2];
                        $flag=false;
						continue;
                    }
                    break;
                case 0://存在即验证
                    if(isset($data[$v[0]])) {
                        if(!$this->check($data[$v[0]],$v[3],$v[4])) {
                            $this->error[] = $v[2];
                            $flag=false;
							continue;
                        }
                    }
                    break;
                case 2://存在并且非空时才验证
                    if(isset($data[$v[0]]) && !empty($data[$v[0]])) {
                        if(!$this->check($data[$v[0]],$v[3],$v[4])) {
                            $this->error[] = $v[2];
                            $flag=false;
							continue;
                        }
                    }
            }
        }
		if($flag==true){
			return $data;
		}else{
			return false;
		}
	}

    protected function check($value,$rule='',$parm='') {
        switch($rule) {
			case 'count':
				list($symbol,$vl)=explode('||',$parm);
				if($symbol=='>') return count($value)>$vl;
				if($symbol=='<') return count($value)<$vl;
				if($symbol=='=') return count($value)==$vl;
				if($symbol=='>=') return count($value)>=$vl;
				if($symbol=='<=') return count($value)<=$vl;
			break;
            case 'gt':
                return intval($value)>intval($parm);
            break;
            case 'egt':
                return intval($value)>=intval($parm);
            break;
            case 'lt':
                return intval($value)<intval($parm);
            break;
            case 'elt':
                return intval($value)<=intval($parm);
            break;
            case 'equal':
                return $value==$parm;
            break;
            case 'require':
                return !empty($value);
            case 'number':
                return is_numeric($value);
            case 'in':
                $tmp = explode(',',$parm);
                return in_array($value,$tmp);
            case 'between':
                list($min,$max) = explode(',',$parm);
                return $value >= $min && $value <= $max;
            case 'length':
				if(!strstr($parm, ',')){
					return mb_strlen($value,'UTF-8') == $parm;
				}else{
					list($min, $max)=explode(',', $parm);
					if(empty($max)){
						return mb_strlen($value,'UTF-8') > $min;
					}else{
						return (mb_strlen($value,'UTF-8')>=$min && mb_strlen($value,'UTF-8') <=$max);
					}
				}
            case 'email':
                return (filter_var($value,FILTER_VALIDATE_EMAIL) !== false);
			case 'regex':
				return preg_match($parm,$value);
			case 'unique':
				if(!$this->_model) return false;
				return (bool) call_user_func_array(array($this->_model,'unique'), array($parm,$value));
			case 'url':
				return preg_match('/^http\:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?$/',$value);
			case 'currency':
				return preg_match('/^\d+(\.\d+)?$/',$value);
			case 'vcode':
				return strtoupper($value)==strtolower($_SESSION[$parm]);
			case 'callback':
				if(!$this->_model) return false;
				return call_user_func_array(array($this->_model,$parm), array($value));
			case 'confirm':
				return $value==$this->_data[$parm];
            default:
                return false;
        }
    }
    public function get_error($return_str=1,$com='<br />'){
        if($return_str==1){
			return implode($com,$this->error);
		}else{
			return $this->error;
		}
    }


}